#include "logger_app.h"

#include "esp_log.h"
#include <cJSON.h>

#include "mqtt_manager.h"
#include "system_info.h"
#include "settings.h"
#include "board.h"
#include "config.h"
#include "ssid_manager.h"


#define TAG "LOGGER_APP"

LoggerApp::LoggerApp() {
    ESP_LOGI(TAG, "初始化日志应用");
    // 记录启动时间
    start_time_ = esp_timer_get_time() / 1000000; // 转换为秒
    // 初始化Settings实例
    settings_ = std::make_unique<Settings>("logger_app", true); // 读写模式
    // 初始化重启信息
    InitializeRebootInfo();
    
    // 新增：初始化日志缓冲区
    log_write_index_ = 0;
    log_count_ = 0;
    memset(log_entries_, 0, sizeof(log_entries_));
    ESP_LOGI(TAG, "日志缓冲区初始化完成，缓冲区大小: %d", LOG_BUFFER_SIZE);
}

bool LoggerApp::start(){

    // 设置日志主题
    sprintf(log_topic,"/c/%s/log/get",SystemInfo::GetMacAddress().c_str());
    if(!MqttManager::GetInstance().SubscribeRealtime(log_topic,1,MqttLog,this)){
        ESP_LOGE(TAG, "启动失败: 订阅主题失败 %s", log_topic);
        return false;
    }
    // 设置统计主题（统一发送统计信息和日志数据）
    sprintf(stats_topic_, "/c/%s/log/send", SystemInfo::GetMacAddress().c_str());

    ESP_LOGI(TAG, "日志应用启动成功");
    return true;
}

void LoggerApp::MqttLog(const char* topic, const char* payload, size_t length, void* user_data) {
    auto* logger = static_cast<LoggerApp*>(user_data); // 类型转换
    
    if (!logger) {
        ESP_LOGE(TAG, "用户数据为空，无法处理日志消息");
        return;
    }
    logger->log(topic, std::string(payload, length));
}

void LoggerApp::log(const std::string& topic, const std::string& payload) {
    // 检查是否是统计指令
    HandleStatsCommand(payload);
    
    // 普通日志输出
    ESP_LOGI(TAG, "收到MQTT消息: %s", payload.c_str());
}

void LoggerApp::HandleStatsCommand(const std::string& payload) {
    // 尝试解析JSON指令
    cJSON* json = cJSON_Parse(payload.c_str());
    if (!json) {
        return;
    }
    
    cJSON* cmd = cJSON_GetObjectItem(json, "cmd");
    if (!cJSON_IsString(cmd)) {
        cJSON_Delete(json);
        return;
    }
    
    std::string command = cmd->valuestring;
    ESP_LOGI(TAG, "执行指令: %s", command.c_str());
    
    if (command == "get_stats") {
        // 发送统计信息
        SendStatistics();
    } else if (command == "reset_stats") {
        // 重置统计信息
        ResetStatistics();
        ESP_LOGI(TAG, "统计数据已重置");
    } else if (command == "reset_reboot_count") {
        // 重置重启次数（特殊指令）
        if (settings_) {
            reboot_count_ = 0;
            SaveRebootCount();
            ESP_LOGI(TAG, "重启次数已重置");
        } else {
            ESP_LOGW(TAG, "Settings未初始化，无法重置重启次数");
        }
    } 
    // 新增：处理日志相关命令
    else if (command == "get_logs") {
        cJSON* count_item = cJSON_GetObjectItem(json, "count");
        size_t max_count = cJSON_IsNumber(count_item) ? count_item->valueint : 50;
        SendLogData(max_count);
    } else if (command == "clear_logs") {
        ClearLogBuffer();
        ESP_LOGI(TAG, "日志缓冲区已清空");
    }
    
    cJSON_Delete(json);
}

// 新增：初始化日志捕获
void LoggerApp::InitializeLogCapture() {
    ESP_LOGI(TAG, "启用日志捕获功能");
    
    // 设置自定义日志输出函数
    esp_log_set_vprintf(CustomLogOutput);
}

// 新增：自定义日志输出函数
int LoggerApp::CustomLogOutput(const char* format, va_list args) {
    // 先调用原始输出（保持控制台正常显示）
    int ret = vprintf(format, args);
    
    // 防止递归和中断问题
    static bool in_logging = false;
    if (in_logging) {
        return ret;
    }
    in_logging = true;
    
    // 格式化完整消息
    static char buffer[256];
    int len = vsnprintf(buffer, sizeof(buffer), format, args);
    
    if (len > 0 && len < sizeof(buffer)) {
        // 移除末尾的换行符
        char* msg = buffer;
        char* newline = strchr(msg, '\n');
        if (newline) *newline = '\0';
        newline = strchr(msg, '\r');
        if (newline) *newline = '\0';
        
        // 只有当消息不为空且不是纯空格时才添加
        if (strlen(msg) > 0) {
            // 跳过纯空格消息
            const char* check = msg;
            while (*check == ' ' || *check == '\t') check++;
            if (*check != '\0') {
                LoggerApp::GetInstance().AddLogEntry(msg);
            }
        }
    }
    
    in_logging = false;
    return ret;
}

// 新增：添加日志条目
void LoggerApp::AddLogEntry(const char* message) {
    // 直接写入，不考虑竞争条件
    SimpleLogEntry* entry = &log_entries_[log_write_index_];
    
    // 复制消息，限制长度
    strncpy(entry->message, message, 99);
    entry->message[99] = '\0';
    
    // 更新索引
    log_write_index_++;
    if (log_write_index_ >= LOG_BUFFER_SIZE) {
        log_write_index_ = 0;  // 循环
    }
    
    // 更新计数
    if (log_count_ < LOG_BUFFER_SIZE) {
        log_count_++;
    }
}

// 新增：发送日志数据
void LoggerApp::SendLogData(size_t max_count) {
    if (log_count_ == 0) {
        ESP_LOGI(TAG, "日志缓冲区为空");
        return;
    }
    
    // 创建JSON
    cJSON* json = cJSON_CreateObject();
    cJSON_AddStringToObject(json, "device_id", SystemInfo::GetMacAddress().c_str());
    cJSON_AddNumberToObject(json, "buffer_logs", log_count_);
    cJSON_AddNumberToObject(json, "buffer_size", LOG_BUFFER_SIZE);
    
    cJSON* logs = cJSON_CreateArray();
    
    // 简化逻辑：按缓冲区顺序发送最新的日志
    size_t to_send = (max_count < log_count_) ? max_count : log_count_;
    
    // 从最新的日志开始发送（write_index前面的是最新的）
    size_t start_index;
    if (log_count_ < LOG_BUFFER_SIZE) {
        // 缓冲区未满，从0开始
        start_index = 0;
    } else {
        // 缓冲区已满，从write_index开始（最老的日志）
        start_index = log_write_index_;
    }
    
    for (size_t i = 0; i < to_send; i++) {
        size_t index = (start_index + i) % LOG_BUFFER_SIZE;
        const SimpleLogEntry* entry = &log_entries_[index];
        
        // 跳过空消息
        if (strlen(entry->message) > 0) {
            cJSON* item = cJSON_CreateObject();
            cJSON_AddStringToObject(item, "msg", entry->message);
            cJSON_AddItemToArray(logs, item);
        }
    }
    
    cJSON_AddItemToObject(json, "logs", logs);
    
    // 发送
    char* json_str = cJSON_Print(json);
    if (json_str) {
        MqttManager::GetInstance().PublishAsync(stats_topic_, json_str, 0);
        ESP_LOGI(TAG, "发送日志 %zu 条", to_send);
        free(json_str);
    }
    
    cJSON_Delete(json);
}

// 新增：清空日志缓冲区
void LoggerApp::ClearLogBuffer() {
    log_write_index_ = 0;
    log_count_ = 0;
    // 不清除内存，只重置索引
}

void LoggerApp::InitializeRebootInfo() {
    // 获取上次重启原因
    last_reset_reason_ = esp_reset_reason();
    std::string reset_reason_str = GetResetReasonString(last_reset_reason_);
    
    if (!settings_) {
        ESP_LOGW(TAG, "Settings未初始化，无法读取重启次数");
        return;
    }
    
    // 从NVS读取重启次数
    reboot_count_ = settings_->GetUint32("reboot_count", 0);
    
    // 递增重启次数
    reboot_count_++;
    
    // 保存新的重启次数
    SaveRebootCount();
    
    ESP_LOGI(TAG, "重启信息: 次数=%lu, 原因=%s", reboot_count_, reset_reason_str.c_str());
}

void LoggerApp::SaveRebootCount() {
    if (!settings_) {
        ESP_LOGW(TAG, "Settings未初始化，无法保存重启次数");
        return;
    }
    
    settings_->SetUint32("reboot_count", reboot_count_);
}

std::string LoggerApp::GetResetReasonString(esp_reset_reason_t reason) {
    switch (reason) {
        case ESP_RST_UNKNOWN:    return "未知原因";
        case ESP_RST_POWERON:    return "上电复位";
        case ESP_RST_EXT:        return "外部复位";
        case ESP_RST_SW:         return "软件复位";
        case ESP_RST_PANIC:      return "异常复位";
        case ESP_RST_INT_WDT:    return "中断看门狗复位";
        case ESP_RST_TASK_WDT:   return "任务看门狗复位";
        case ESP_RST_WDT:        return "其他看门狗复位";
        case ESP_RST_DEEPSLEEP:  return "深度睡眠唤醒";
        case ESP_RST_BROWNOUT:   return "欠压复位";
        case ESP_RST_SDIO:       return "SDIO复位";
        default:                 return "未定义原因";
    }
}

// WiFi信息记录方法实现
void LoggerApp::RecordWifiScanResults(const std::vector<WifiScanResult>& scan_results) {
    wifi_scan_results_ = scan_results;
    last_wifi_scan_time_ = esp_timer_get_time() / 1000000; // 转换为秒
    
    ESP_LOGI(TAG, "WiFi扫描完成: 发现 %zu 个网络", wifi_scan_results_.size());
}

void LoggerApp::RecordConfiguredSsids(const std::vector<std::string>& ssid_list) {
    configured_ssids_ = ssid_list;
    ESP_LOGI(TAG, "已配置SSID: %zu 个", configured_ssids_.size());
}

// 统计记录方法实现 - 移除调试输出
void LoggerApp::RecordNvsWrite() {
    nvs_write_count_++;
}

void LoggerApp::RecordWifiError() {
    wifi_error_count_++;
}

void LoggerApp::RecordMqttError() {
    mqtt_error_count_++;
}

void LoggerApp::RecordRelayError() {
    relay_error_count_++;
}

void LoggerApp::RecordSystemWarning() {
    system_warning_count_++;
}

void LoggerApp::RecordOtaAttempt() {
    ota_attempt_count_++;
}

void LoggerApp::RecordOtaError() {
    ota_error_count_++;
}

void LoggerApp::SendStatistics() {
    // 创建简化的JSON统计数据
    cJSON* stats = cJSON_CreateObject();
    if (!stats) {
        ESP_LOGE(TAG, "创建JSON对象失败");
        return;
    }
    
    // 基本信息
    uint32_t current_time = esp_timer_get_time() / 1000000; // 转换为秒
    uint32_t uptime = current_time - start_time_;
    
    cJSON_AddStringToObject(stats, "device_id", SystemInfo::GetMacAddress().c_str());
    cJSON_AddStringToObject(stats, "Version", VERSION);
    cJSON_AddNumberToObject(stats, "device_5id", Board::GetInstance().ReadDipSwitch());
    cJSON_AddNumberToObject(stats, "timestamp", current_time);
    cJSON_AddNumberToObject(stats, "uptime_seconds", uptime);
    
    // 重启信息
    cJSON_AddNumberToObject(stats, "reboot_count", reboot_count_);
    cJSON_AddStringToObject(stats, "last_reset_reason", GetResetReasonString(last_reset_reason_).c_str());
    
    // 操作统计
    cJSON_AddNumberToObject(stats, "nvs_writes", nvs_write_count_);
    
    // 错误统计
    cJSON_AddNumberToObject(stats, "wifi_errors", wifi_error_count_);
    cJSON_AddNumberToObject(stats, "mqtt_errors", mqtt_error_count_);
    cJSON_AddNumberToObject(stats, "relay_errors", relay_error_count_);
    cJSON_AddNumberToObject(stats, "system_warnings", system_warning_count_);
    
    // OTA统计
    cJSON_AddNumberToObject(stats, "ota_attempts", ota_attempt_count_);
    cJSON_AddNumberToObject(stats, "ota_errors", ota_error_count_);
    
    // WiFi信息
    cJSON* wifi_info = cJSON_CreateObject();
    
    // 已配置的SSID列表
    cJSON* configured_ssids = cJSON_CreateArray();
    for (const auto& ssid : configured_ssids_) {
        cJSON_AddItemToArray(configured_ssids, cJSON_CreateString(ssid.c_str()));
    }
    cJSON_AddItemToObject(wifi_info, "configured_ssids", configured_ssids);
    
    // WiFi扫描结果
    cJSON* scan_results = cJSON_CreateArray();
    for (const auto& result : wifi_scan_results_) {
        cJSON* scan_item = cJSON_CreateObject();
        cJSON_AddStringToObject(scan_item, "ssid", result.ssid.c_str());
        cJSON_AddNumberToObject(scan_item, "rssi", result.rssi);
        cJSON_AddStringToObject(scan_item, "auth_mode", result.auth_mode.c_str());
        cJSON_AddItemToArray(scan_results, scan_item);
    }
    cJSON_AddItemToObject(wifi_info, "scan_results", scan_results);
    cJSON_AddNumberToObject(wifi_info, "last_scan_time", last_wifi_scan_time_);
    cJSON_AddNumberToObject(wifi_info, "scan_count", wifi_scan_results_.size());
    
    cJSON_AddItemToObject(stats, "wifi_info", wifi_info);
    
    // 新增：日志缓冲区统计
    cJSON_AddNumberToObject(stats, "log_buffer_count", log_count_);
    cJSON_AddNumberToObject(stats, "log_buffer_size", LOG_BUFFER_SIZE);
    
    // 转换为字符串并发送
    char* json_string = cJSON_Print(stats);
    if (json_string) {
        auto& mqtt_manager = MqttManager::GetInstance();
        mqtt_manager.PublishAsync(stats_topic_, json_string, 0);
        
        ESP_LOGI(TAG, "统计信息已发送: 运行时间=%lus, 重启=%lu次, WiFi=%zu个, 日志=%zu条", 
                 uptime, reboot_count_, wifi_scan_results_.size(), log_count_);
        
        free(json_string);
    } else {
        ESP_LOGE(TAG, "JSON字符串转换失败");
    }
    
    cJSON_Delete(stats);
}

void LoggerApp::ResetStatistics() {
    nvs_write_count_ = 0;
    wifi_error_count_ = 0;
    mqtt_error_count_ = 0;
    relay_error_count_ = 0;
    system_warning_count_ = 0;
    ota_attempt_count_ = 0;
    ota_error_count_ = 0;
    
    // 清除WiFi扫描结果，但保留已配置的SSID
    wifi_scan_results_.clear();
    last_wifi_scan_time_ = 0;
    
    // 注意：重启次数和重启原因不应该被重置，因为这些是持久的系统信息
    
    start_time_ = esp_timer_get_time() / 1000000; // 重置启动时间
    
    ESP_LOGI(TAG, "统计数据已重置");
}

